package com.koron.operation.classes.schedule.service.impl;


import com.github.pagehelper.PageInfo;
import com.koron.bean.query.PageQuery;
import com.koron.operation.classes.schedule.bean.dto.ClassesScheduleDTO;
import com.koron.operation.classes.schedule.bean.dto.ClassesShiftDTO;
import com.koron.operation.classes.schedule.bean.dto.ScheduleDTO;
import com.koron.operation.classes.schedule.bean.po.ClassesSchedule;
import com.koron.operation.classes.schedule.bean.po.ClassesShift;
import com.koron.operation.classes.schedule.bean.po.ClassesStaff;
import com.koron.operation.classes.schedule.bean.query.ScheduleQuery;
import com.koron.operation.classes.schedule.mapper.ClassesScheduleMapper;
import com.koron.operation.classes.schedule.service.ClassesScheduleService;
import com.koron.operation.classes.schedule.service.ClassesShiftService;
import com.koron.operation.classes.schedule.service.ClassesStaffService;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.TaskAnnotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 排班方案(ClassesSchedule)表服务实现类
 *
 * @author jzp
 * @since 2021-10-20 16:20:35
 */
@Service
public class ClassesScheduleServiceImpl implements ClassesScheduleService {
    @Autowired
    private ClassesShiftService shiftService;

    @Autowired
    private ClassesStaffService staffService;

    /**
     * 通过ID查询单条数据
     */
    @Override
    @TaskAnnotation("getById")
    public ClassesSchedule getById(SessionFactory factory, String id) {
        ClassesScheduleMapper mapper = factory.getMapper(ClassesScheduleMapper.class);
        return mapper.selectById(id);
    }

    @Override
    @TaskAnnotation("getDtoById")
    public ScheduleDTO getDtoById(SessionFactory factory, String id) {
        ClassesScheduleMapper mapper = factory.getMapper(ClassesScheduleMapper.class);
        ClassesScheduleDTO classesScheduleDTO = mapper.selectDtoById(id);
        ScheduleDTO scheduleDTO = new ScheduleDTO();
        scheduleDTO.fromClassesScheduleDTO(classesScheduleDTO);
        return scheduleDTO;
    }

    /**
     * 查询所有数据
     */
    @Override
    @TaskAnnotation("list")
    public List<ClassesSchedule> list(SessionFactory factory, ScheduleQuery query) {
        ClassesScheduleMapper mapper = factory.getMapper(ClassesScheduleMapper.class);
        return mapper.selectList(query);
    }

    @Override
    @TaskAnnotation("listHealth")
    public List<ClassesSchedule> listHealth(SessionFactory factory, ScheduleQuery query) {
        ClassesScheduleMapper mapper = factory.getMapper(ClassesScheduleMapper.class);
        return mapper.selectHealthList(query);
    }

    @Override
    @TaskAnnotation("listDto")
    public List<ClassesScheduleDTO> listDto(SessionFactory factory, ScheduleQuery query) {
        ClassesScheduleMapper mapper = factory.getMapper(ClassesScheduleMapper.class);
        return mapper.selectDtoList(query);
    }

    @Override
    @TaskAnnotation("listNoStaffDto")
    public List<ClassesScheduleDTO> listNoStaffDto(SessionFactory factory, ScheduleQuery query) {
        ClassesScheduleMapper mapper = factory.getMapper(ClassesScheduleMapper.class);
        return mapper.selectNoStaffDtoList(query);
    }

    @Override
    @TaskAnnotation("page")
    public PageInfo<ClassesSchedule> page(SessionFactory factory, PageQuery pageQuery, ScheduleQuery query) {
        pageQuery.getOrders().forEach(e -> e.setPrefix("classesSchedule"));
        return ClassesScheduleService.super.page(factory, pageQuery, query);
    }

    /**
     * 新增数据
     */
    @Override
    @TaskAnnotation("save")
    public boolean save(SessionFactory factory, ClassesSchedule classesSchedule) {
        ClassesScheduleMapper mapper = factory.getMapper(ClassesScheduleMapper.class);
        Assert.notNull(classesSchedule.getClassesId(), "未关联班别方案");
        // 默认启用
        if (classesSchedule.getStatus() == null) {
            classesSchedule.setStatus(0);
        }
        return mapper.insert(classesSchedule) > 0;
    }

    @Override
    @TaskAnnotation("saveOrUpdateDto")
    public boolean saveOrUpdateDto(SessionFactory factory, ScheduleDTO scheduleDTO) {
        // 1. 保存或更新基本数据
        if (StringUtils.isEmpty(scheduleDTO.getId())) {
            save(factory, scheduleDTO);
        } else {
            update(factory, scheduleDTO);
        }

        // 2. 保存排班明细
        // 2.1. 删除所有班别明细数据
        shiftService.removeByScheduleId(factory, scheduleDTO.getId());
        // 2.2. 设置scheduleId、sort
        List<ClassesShift> classesShifts = new ArrayList<>();
        List<ClassesShiftDTO> classesShiftDTOs = scheduleDTO.toClassesShiftDTOs();
        AtomicInteger atomicInteger = new AtomicInteger(0);
        for (ClassesShiftDTO classesShiftDTO : classesShiftDTOs) {
            classesShiftDTO.setScheduleId(scheduleDTO.getId());
            classesShiftDTO.setSort(atomicInteger.getAndIncrement());
            if (classesShiftDTO.getStatus() == null) {
                // status为null则设置为0未接班
                classesShiftDTO.setStatus(0);
            }
            classesShifts.add(classesShiftDTO);
        }
        // 2.3. 保存所有班别明细数据
        shiftService.saveBatch(factory, classesShifts);

        // 3. 保存或更新人员信息
        // 3.1. 删除所有人员信息数据
        staffService.removeByScheduleId(factory, scheduleDTO.getId());
        // 3.2. 设置scheduleId、shiftId
        List<ClassesStaff> classesStaffs = new ArrayList<>();
        for (int i = 0; i < classesShifts.size(); i++) {
            ClassesShift classesShift = classesShifts.get(i);
            List<ClassesStaff> staffs = classesShiftDTOs.get(i).getStaffs();
            if (!CollectionUtils.isEmpty(staffs)) {
                for (ClassesStaff staff : staffs) {
                    staff.setScheduleId(classesShift.getScheduleId());
                    staff.setShiftId(classesShift.getId());
                }
                classesStaffs.addAll(staffs);
            }
        }
        // 3.3. 保存所有人员信息
        return staffService.saveBatch(factory, classesStaffs);
    }

    @Override
    @TaskAnnotation("hasDuplicate")
    public List<ClassesSchedule> hasDuplicate(SessionFactory factory, ScheduleDTO scheduleDTO) {
        ScheduleQuery scheduleQuery = new ScheduleQuery();
        scheduleQuery.setDeptId(scheduleDTO.getDeptId());
        scheduleQuery.setLocationId(scheduleDTO.getLocationId());
        scheduleQuery.setStaffTypes(Collections.singletonList(scheduleDTO.getStaffType()));
        scheduleQuery.setStatus(Collections.singletonList(0));
        List<ClassesSchedule> list = list(factory, scheduleQuery);
        if (!CollectionUtils.isEmpty(list)) {
            Date thisStartTime = scheduleDTO.getStartTime();
            Date thisEndTime = scheduleDTO.getEndTime();
            if (thisEndTime == null) {
                return new ArrayList<>();
            }
            return list.stream()
                    .sorted(Comparator.comparing(ClassesSchedule::getStartTime))
                    .filter(classesSchedule -> !Objects.equals(scheduleDTO.getId(), classesSchedule.getId()) && classesSchedule.getEndTime() != null && thisStartTime.before(classesSchedule.getEndTime()) && thisEndTime.after(classesSchedule.getStartTime()))
                    .collect(Collectors.toList());
        }

        return new ArrayList<>();
    }

    /**
     * 修改数据
     */
    @Override
    @TaskAnnotation("update")
    public boolean update(SessionFactory factory, ClassesSchedule classesSchedule) {
        ClassesScheduleMapper mapper = factory.getMapper(ClassesScheduleMapper.class);
        return mapper.update(classesSchedule) > 0;
    }

    @Override
    @TaskAnnotation("updateStatus")
    public boolean updateStatus(SessionFactory factory, String id, Integer status) {
        ClassesScheduleMapper mapper = factory.getMapper(ClassesScheduleMapper.class);
        ClassesSchedule classesSchedule = new ClassesSchedule();
        classesSchedule.setId(id);
        classesSchedule.setStatus(status);
        return mapper.update(classesSchedule) > 0;
    }

    /**
     * 通过主键删除数据
     */
    @Override
    @TaskAnnotation("deleteById")
    public boolean deleteById(SessionFactory factory, String id) {
        ClassesScheduleMapper mapper = factory.getMapper(ClassesScheduleMapper.class);
        return mapper.hidden(id) > 0;
    }
}
